﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace GameJamSnake
{


    class Segment
    {
        protected int m_xPos;
        protected int m_yPos;
        protected int m_oldXPos;
        protected int m_oldYPos;
        protected Texture2D m_image;
        protected Texture2D m_power;
        protected Texture2D m_elbow;
        protected Texture2D m_tail;
        protected Texture2D m_middle;
        protected int m_myPosinList;

        protected bool edible = false;
        bool m_powerUp = false;


        public const int START_LENGTH = 8;

        /*public Segment()
        {
            m_xPos = 0;
            m_yPos = 0;
            //m_orientation = 0;
        }*/

        public Segment(int xPos, int yPos,int posInChain)
        {
            m_xPos = xPos;
            m_yPos = yPos;
            m_myPosinList = posInChain;
        }

        public void Load(Texture2D tex, Texture2D pow)
        {
            m_image = tex;
            m_power = pow;
        }
        public void Load(Texture2D tex)
        {
            m_image = tex;
        }
        private bool Clockwise(Vector2 back, Vector2 front, Vector2 centre)
        {
            Vector2 FromBack = centre - back;
            FromBack.Normalize();

            Vector2 ToFront = front - centre;
            ToFront.Normalize();
            

            float cross = (FromBack.X*ToFront.Y) - (ToFront.X * FromBack.Y);
 
            if (cross > 0)
            {
                return true;
            }

            return false;

        }

        public void MakeEdible()
        {
            edible = true;
        }

        public bool GetEdibleness()
        {
            return edible;
        }

        public void PowerUp()
        {
            m_powerUp = true;
        }

        public void PowerDown()
        {
            m_powerUp = false;
            Scorekeeper.Instance.PowerOver(true);
        }

        public bool GetPowerState()
        {
            return m_powerUp;
        }

        public int GetListPos()
        {
            return m_myPosinList;
        }

        public void SetListPos(int newPos)
        {
            m_myPosinList = newPos;
        }

        public void Respawn(Tile[,] tiles)
        {
            Random rand = new Random();

            while (true)
            {
                bool fail = false;

                m_xPos = rand.Next(Game1.SCREEN_WIDTH / Tile.CELL_WIDTH);
                m_yPos = rand.Next(Game1.SCREEN_HEIGHT / Tile.CELL_HEIGHT);

                if (tiles[m_xPos / Tile.CELL_WIDTH, m_yPos / Tile.CELL_HEIGHT].GetState() == Tile.TileState.EMPTY)
                {
                    for (int i = 0; i < Game1.SCREEN_WIDTH / Tile.CELL_WIDTH; ++i)
                    {
                        for (int j = 0; j < Game1.SCREEN_HEIGHT / Tile.CELL_HEIGHT; ++j)
                        {
                            if (tiles[i, j].GetState() == Tile.TileState.STONE)
                            {
                                if (tiles[i, j].GetRectangle().Intersects(tiles[m_xPos / Tile.CELL_WIDTH, m_yPos / Tile.CELL_HEIGHT].GetRectangle()))
                                    fail = true;
                            }
                        }
                    }
                }

                if (!fail)
                {
                    m_xPos *= Tile.CELL_WIDTH;
                    m_yPos *= Tile.CELL_HEIGHT;
                    break;
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch, List<Segment> snake,Segment head,bool colorBlind)
        {
            Rectangle srcRect = new Rectangle(0, 0, Tile.CELL_WIDTH, Tile.CELL_HEIGHT);
            Rectangle destRect = new Rectangle(m_xPos + 20, m_yPos + 20, Tile.CELL_WIDTH, Tile.CELL_HEIGHT);

            Vector2 myFront;

            if (m_myPosinList != 0)
            {
                myFront.X = snake[m_myPosinList - 1].GetXPos();
                myFront.Y = snake[m_myPosinList - 1].GetYPos();
            }
            else
            {
                myFront.X = head.GetXPos();
                myFront.Y = head.GetYPos();
            }

            Vector2 myBack;

            Vector2 myCentre;

            myCentre.X = m_xPos;
            myCentre.Y = m_yPos;

            if (m_myPosinList != snake.Count -1)
            {
                myBack.X = snake[m_myPosinList + 1].GetXPos();
                myBack.Y = snake[m_myPosinList + 1].GetYPos();
            }
            else
            {
                myBack.X = m_xPos;
                myBack.Y = m_yPos;
            }

            Vector2 directionVec = myFront - myBack;

            directionVec.Normalize();

            bool isElbow = false;

            if (Math.Abs(directionVec.X) == Math.Abs(directionVec.Y))
            {
                isElbow = true;
            }

            double angle = Math.Atan2(directionVec.X, directionVec.Y);
            Vector2 origin;
            origin.X = TextureManager.Instance.GetTex("Middle").Width/2;
            origin.Y = TextureManager.Instance.GetTex("Middle").Height/2;

           

            if (!isElbow)
            {
                if (angle == 0)
                {
                    angle = Math.PI * 2;
                }

                if (angle == Math.PI*2)
                {
                    angle = 0;
                }

                if (Math.Abs(angle) == Math.PI /2)
                {
                    angle *= -1;
                }

                if(m_myPosinList == snake.Count - 1)
                {
                    if (!edible)
                    {
                        spriteBatch.Draw(TextureManager.Instance.GetTex("Tail"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                    } 
                    else
                    {
                        if (colorBlind)
                        {
                            spriteBatch.Draw(TextureManager.Instance.GetTex("Tail"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                            spriteBatch.Draw(TextureManager.Instance.GetTex("Marker"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                        } 
                        else
                        {
                            spriteBatch.Draw(TextureManager.Instance.GetTex("Tail"), destRect, null, Color.Red, (float)angle, origin, SpriteEffects.None, 0f);
                        }
                        
                    }
                    
                }
                else
                {
                    if (!edible)
                    {
                        spriteBatch.Draw(TextureManager.Instance.GetTex("Middle"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                    }
                    else
                    {
                        if (colorBlind)
                        {
                            spriteBatch.Draw(TextureManager.Instance.GetTex("Middle"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                            spriteBatch.Draw(TextureManager.Instance.GetTex("Marker"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);  
                        }
                        else
                        {
                            spriteBatch.Draw(TextureManager.Instance.GetTex("Middle"), destRect, null, Color.Black, (float)angle, origin, SpriteEffects.None, 0f);
                        }
                    } 
                }

            } 
            else
            {
                //Right to down
                if (directionVec.X > 0 && directionVec.Y > 0)
                {
                    if (Clockwise(myBack, myFront, myCentre))
                    {
                        angle = 0;
                    }
                    else
                    {
                        angle = -Math.PI;
                    }
                }

                //Down to left
                if (directionVec.X < 0 && directionVec.Y > 0)
                {
                    if (Clockwise(myBack, myFront, myCentre))
                    {
                        angle = Math.PI / 2;
                    }
                    else
                    {
                        angle = -Math.PI / 2;
                    }

                }
                // Left to Up
                if (directionVec.X < 0 && directionVec.Y < 0)
                {
                    if (Clockwise(myBack, myFront, myCentre))
                    {
                        angle = -Math.PI;
                    }
                    else
                    {
                        angle = 0;
                    }
                    
                }

                if (directionVec.X > 0 && directionVec.Y < 0)
                {
                    if (Clockwise(myBack, myFront, myCentre))
                    {
                        angle = -Math.PI / 2;
                    } 
                    else
                    {
                        angle = Math.PI/2;
                    }
                    
                }


                if (!edible)
                {
                    spriteBatch.Draw(TextureManager.Instance.GetTex("Elbow"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                }
                else
                {
                    if (colorBlind)
                    {
                        spriteBatch.Draw(TextureManager.Instance.GetTex("Elbow"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                        spriteBatch.Draw(TextureManager.Instance.GetTex("Marker"), destRect, null, Color.White, (float)angle, origin, SpriteEffects.None, 0f);
                    }
                    else
                    {
                        spriteBatch.Draw(TextureManager.Instance.GetTex("Elbow"), destRect, null, Color.Red, (float)angle, origin, SpriteEffects.None, 0f);
                    }
                } 
            }
              
        }
        public void Draw(SpriteBatch spriteBatch,  int orientation)
        {
            Rectangle srcRect = new Rectangle(0, 0, Tile.CELL_WIDTH, Tile.CELL_HEIGHT);
            Rectangle destRect = new Rectangle(m_xPos + (Tile.CELL_WIDTH / 2), m_yPos + (Tile.CELL_WIDTH / 2), Tile.CELL_WIDTH, Tile.CELL_HEIGHT);

            Color textureColour = new Color();
            if (m_powerUp)
                textureColour = Color.White;
            else
                textureColour = Color.White;
            if (!m_powerUp)
            {
                if (orientation == 1)
                {
                    spriteBatch.Draw(m_image, destRect, new Rectangle(0, 0, 40, 40), textureColour, 90, new Vector2(20, 20), SpriteEffects.FlipHorizontally, 1.0f);
                }
                else if (orientation == 2)
                {
                    spriteBatch.Draw(m_image, destRect, new Rectangle(0, 0, 40, 40), textureColour, 0, new Vector2(20, 20), SpriteEffects.None, 1.0f);
                }
                else if (orientation == 3)
                {
                    spriteBatch.Draw(m_image, destRect, new Rectangle(0, 0, 40, 40), textureColour, 90, new Vector2(20, 20), SpriteEffects.None, 1.0f);
                }
                else if (orientation == 0)
                {
                    spriteBatch.Draw(m_image, destRect, new Rectangle(0, 0, 40, 40), textureColour, 0, new Vector2(20, 20), SpriteEffects.FlipHorizontally, 1.0f);
                }
            }
            else
            {
                if (orientation == 1)
                {
                    spriteBatch.Draw(m_power, destRect, new Rectangle(0, 0, 40, 40), textureColour, 90, new Vector2(20, 20), SpriteEffects.FlipHorizontally, 1.0f);
                }
                else if (orientation == 2)
                {
                    spriteBatch.Draw(m_power, destRect, new Rectangle(0, 0, 40, 40), textureColour, 0, new Vector2(20, 20), SpriteEffects.None, 1.0f);
                }
                else if (orientation == 3)
                {
                    spriteBatch.Draw(m_power, destRect, new Rectangle(0, 0, 40, 40), textureColour, 90, new Vector2(20, 20), SpriteEffects.None, 1.0f);
                }
                else if (orientation == 0)
                {
                    spriteBatch.Draw(m_power, destRect, new Rectangle(0, 0, 40, 40), textureColour, 0, new Vector2(20, 20), SpriteEffects.FlipHorizontally, 1.0f);
                }
            }
        }

        public Rectangle GetRectangle()
        {
            Rectangle rect = new Rectangle(m_xPos, m_yPos, Tile.CELL_WIDTH, Tile.CELL_HEIGHT);
            return rect;
        }

        public int GetXReference()
        {
             return m_xPos / Tile.CELL_WIDTH;
        }

        public int GetYReference()
        {
            return m_yPos / Tile.CELL_HEIGHT;
        }

        public void Update(GameTime gameTime, int newXPos, int newYPos)
        {
            m_oldXPos = m_xPos;
            m_oldYPos = m_yPos;
            m_xPos = newXPos;
            m_yPos = newYPos;

            if (m_xPos < 0)
            {
                m_xPos = Game1.SCREEN_WIDTH - Tile.CELL_WIDTH;
            }
            else if (m_xPos > Game1.SCREEN_WIDTH - Tile.CELL_WIDTH)
            {
                m_xPos = 0;
            }

            if (m_yPos < 0)
            {
                m_yPos = Game1.SCREEN_HEIGHT - Tile.CELL_HEIGHT;
            }
            else if (m_yPos > Game1.SCREEN_HEIGHT - Tile.CELL_HEIGHT)
            {
                m_yPos = 0;
            }
        }

        public void Update(GameTime gameTime, int orientation)
        {
            m_oldXPos = m_xPos;
            m_oldYPos = m_yPos;

            if (orientation == 0)
            {
                m_xPos += Tile.CELL_WIDTH;
            }
            else if (orientation == 2)
            {
                m_xPos -= Tile.CELL_WIDTH;
            }

            if (orientation == 1)
            {
                m_yPos += Tile.CELL_HEIGHT;
            }
            else if (orientation == 3)
            {
                m_yPos -= Tile.CELL_HEIGHT;
            }

            if (m_xPos < 0)
            {
                m_xPos = Game1.SCREEN_WIDTH - Tile.CELL_WIDTH;
            }
            else if (m_xPos > Game1.SCREEN_WIDTH - Tile.CELL_WIDTH)
            {
                m_xPos = 0;
            }

            if (m_yPos < 0)
            {
                m_yPos = Game1.SCREEN_HEIGHT - Tile.CELL_HEIGHT;
            }
            else if (m_yPos > Game1.SCREEN_HEIGHT - Tile.CELL_HEIGHT)
            {
                m_yPos = 0;
            }
        }

        public int GetXPos()
        {
            return m_xPos;
        }

        public int GetYPos()
        {
            return m_yPos;
        }

        public int GetOldX()
        {
            return m_oldXPos;
        }

        public int GetOldY()
        {
            return m_oldYPos;
        }
    }
}
